import axios, {AxiosRequestHeaders, AxiosResponse, ResponseType} from 'axios'
import qs from 'qs'
import {ElMessage, ElMessageBoxOptions} from 'element-plus'
import {AxiosPromise} from "@/types/common";

// axios实例
const service = axios.create({
    baseURL: import.meta.env.VITE_APP_BASE_API,
    timeout: 60000,
    headers: {'Content-Type': 'application/json;charset=UTF-8'}
})

// 请求拦截器
service.interceptors.request.use(
    (config: any) => {
        // 追加时间戳，防止GET请求缓存
        if (config.method?.toUpperCase() === 'GET') {
            config.params = {...config.params, t: new Date().getTime()}
        }

        if (Object.values(config.headers).includes('application/x-www-form-urlencoded')) {
            config.data = qs.stringify(config.data)
        }

        return config
    },
    error => {
        return Promise.reject(error)
    }
)

// 响应拦截器
service.interceptors.response.use(
    response => {
        if (response.status !== 200) {
            return Promise.reject(new Error(response.statusText || 'Error'))
        }

        const data = response.data
        // 响应成功
        if (data.code === 1) {
            return data
        }
        console.log(data.type)
        console.log(data.code !== 0)
        // 如果是流数据则下载
        if ((data instanceof ArrayBuffer || data instanceof Blob)) {
            handleDownload(response)
            return data;
        }

        // 错误提示
        ElMessage.error(data.msg)

        return Promise.reject(new Error(data.msg || 'Error'))
    },
    error => {
        ElMessage.error(error.message)
        return Promise.reject(error)
    }
)

/**
 * 处理下载文件
 * @param response 响应
 */
function handleDownload(response: AxiosResponse) {
    if (response.data.type === 'application/json') {
        //此时返回的data为blob格式
        const file=new FileReader();//读取文件
        file.readAsText(response.data,'utf-8');//读取文件，并设置编码格式为utf-8
        file.onload=function(){//在读取文件操作完成后触发
            const message = JSON.parse(file.result as string);
            ElMessage.error(message.msg)
        }
        return
    }
    // 创建 二进制 数据
    const blob = new Blob([response.data], {type: response.headers['content-type']});
    const a = document.createElement('a');
    // 下载的链接
    const href = window.URL.createObjectURL(blob);
    a.href = href;
    // 获取后台设置的文件名称, 去除文件名前后的双引号
    let fileName = response.headers['content-disposition'].split(';')[1].split('=')[1];
    if (fileName.startsWith("\"")) {
        fileName = fileName.substring(1)
    }
    if (fileName.endsWith("\"")) {
        fileName = fileName.substring(0, fileName.length - 1)
    }
    // 解码 URI
    a.download = decodeURI(fileName);
    document.body.appendChild(a);
    // 点击导出
    a.click();
    // 下载完成移除元素
    document.body.removeChild(a);
    // 释放掉blob对象
    window.URL.revokeObjectURL(href);
}

/**
 * get 请求
 * @param url 请求地址
 * @param params 请求数据
 * @param headers 请求头
 */
const get = <T>(url: string, params: object = {}, headers: AxiosRequestHeaders = {}): AxiosPromise<T> =>
    service({
        url: url,
        headers,
        method: 'get',
        params: {...params}
    }).then(result => {
        return result as any
    })

/**
 * post 请求
 * @param url 请求地址
 * @param data 请求数据
 * @param headers 请求头
 */
const post = <T>(url: string, data: object = {}, headers: AxiosRequestHeaders = {}): AxiosPromise<T> => service({
    url: url,
    headers,
    method: 'post',
    data
}).then(result => {
    return result as any
})

/**
 * delete 请求
 * @param url 请求地址
 * @param params 请求数据
 * @param headers 请求头
 */
const deleted = <T>(url: string, params: object = {}, headers: AxiosRequestHeaders = {}): AxiosPromise<T> => service({
    url: url,
    headers,
    method: 'delete',
    params
}).then(result => {
    return result as any
})

/**
 * put 请求
 * @param url 请求地址
 * @param data 请求数据
 * @param headers 请求头
 */
const put = <T>(url: string, data: object = {}, headers: AxiosRequestHeaders = {}): AxiosPromise<T> => service({
    url: url,
    headers,
    method: 'put',
    data
}).then(result => {
    return result as any
})

/**
 * patch 请求
 * @param url 请求地址
 * @param data 请求数据
 * @param headers 请求头
 */
const patch = <T>(url: string, data: object = {}, headers: AxiosRequestHeaders = {}): AxiosPromise<T> => service({
    url: url,
    headers,
    method: 'patch',
    data
}).then(result => {
    return result as any
})

/**
 * 请求
 */
const request = (params: object = {}) => service(params)

/**
 * post 请求
 * @param url 请求地址
 * @param data 请求数据
 */
const upload = <T>(url: string, data: object = {}): AxiosPromise<T> => service({
    url: url,
    headers: {"content-type": "multipart/form-data"},
    method: 'post',
    data
}).then(result => {
    return result as any
})

/**
 * 下载文件
 * @param url 下载地址
 * @param params 数据
 * @param responseType 响应类型
 */
const download = (url: string, params: object = {}, responseType?: ResponseType) => service({
    url: url,
    method: 'get',
    params,
    responseType
})

/**
 * 下载文件
 * @param url 下载地址
 * @param params 数据
 */
const downloadByBlob = (url: string, params: object = {}) => service({
    url: url,
    method: 'get',
    params,
    responseType: 'blob'
})

/**
 * 下载文件
 * @param url 下载地址
 * @param params 数据
 */
const downloadWithBuffer = (url: string, params: object = {}) => download(url, params, 'arraybuffer')

// 导出 axios 实例
export {
    get,
    post,
    deleted,
    put,
    patch,
    request,
    upload,
    download,
    downloadByBlob,
    downloadWithBuffer
}

